home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_024 / csh / execom.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  10KB  |  439 lines

  1.  
  2. /*
  3.  * EXECOM.C
  4.  *
  5.  * Matthew Dillon, 28 Apr 1986
  6.  *
  7.  *    This code is particular hacked up and needs re-writing.
  8.  *
  9.  */
  10.  
  11. #include "shell.h"
  12.  
  13.  
  14. struct COMMAND {
  15.    int (*func)();
  16.    short minargs;
  17.    short stat;
  18.    short val;
  19.    char *name;
  20. };
  21.  
  22. struct MLIST {
  23.    struct MLIST *next;
  24. };
  25.  
  26. #define F_EXACT   0
  27. #define F_ABBR    1
  28.  
  29. extern char *breakout();
  30.  
  31. extern int do_run(), do_number();
  32. extern int do_quit(), do_set_var(), do_unset_var();
  33. extern int do_echo(), do_source(), do_mv();
  34. extern int do_cd(), do_rm(), do_mkdir(), do_history();
  35. extern int do_mem(), do_cat(), do_dir();
  36. extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
  37. extern int do_failat(), do_checkbrk(), do_inc();
  38. extern int do_input(), do_ver();
  39.  
  40. static struct MLIST *Mlist;
  41.  
  42. static struct COMMAND Command[] = {
  43.    do_run      , 0,  0,          0 ,   "\001",
  44.    do_number   , 0,  0,          0 ,   "\001",
  45.    do_quit     , 0,  0,          0 ,   "quit",
  46.    do_set_var  , 0,  0, LEVEL_SET  ,   "set",
  47.    do_unset_var, 0,  0, LEVEL_SET  ,   "unset",
  48.    do_set_var  , 0,  0, LEVEL_ALIAS,   "alias",
  49.    do_unset_var, 0,  0, LEVEL_ALIAS,   "unalias",
  50.    do_echo     , 0,  0,          0 ,   "echo",
  51.    do_source   , 0,  0,          0 ,   "source",
  52.    do_mv       , 2,  0,          0 ,   "mv",
  53.    do_cd       , 0,  0,          0 ,   "cd",
  54.    do_rm       , 0,  0,          0 ,   "rm",
  55.    do_mkdir    , 0,  0,          0 ,   "mkdir",
  56.    do_history  , 0,  0,          0 ,   "history",
  57.    do_mem      , 0,  0,          0 ,   "mem",
  58.    do_cat      , 0,  0,          0 ,   "cat",
  59.    do_dir      , 0,  0,          0 ,   "dir",
  60.    do_dir      , 0,  0,         -1 ,   "devinfo",
  61.    do_foreach  , 3,  0,          0 ,   "foreach",
  62.    do_return   , 0,  0,          0 ,   "return",
  63.    do_if       , 1,  1,          0 ,   "if",
  64.    do_if       , 0,  1,          1 ,   "else",
  65.    do_if       , 0,  1,          2 ,   "endif",
  66.    do_label    , 1,  1,          0 ,   "label",
  67.    do_goto     , 1,  0,          0 ,   "goto",
  68.    do_failat   , 1,  0,          0 ,   "failat",
  69.    do_checkbrk , 0,  0,          0 ,   "checkbreak",
  70.    do_inc      , 1,  0,          1 ,   "inc",
  71.    do_inc      , 1,  0,          -1,   "dec",
  72.    do_input    , 1,  0,          0,    "input",
  73.    do_ver      , 0,  0,          0,    "version",
  74.    NULL        , 0,  0,          0 ,   NULL };
  75.  
  76. static char *
  77. mpush(amount)
  78. {
  79.    struct MLIST *ml;
  80.  
  81.    ml = (struct MLIST *)malloc (amount + sizeof(*Mlist));
  82.    ml->next = Mlist;
  83.    Mlist = ml;
  84.    return ((char *)Mlist + sizeof(*Mlist));
  85. }
  86.  
  87. static char *
  88. mpop()
  89. {
  90.    char *old = NULL;
  91.  
  92.    if (Mlist == NULL) {
  93.       puts ("Internal MLIST error");
  94.       fflush (stdout);
  95.    } else {
  96.       old = (char *)Mlist + sizeof(*Mlist);
  97.       Free (Mlist);
  98.       Mlist = Mlist->next;
  99.    }
  100.    return (old);
  101. }
  102.  
  103. mrm()
  104. {
  105.    while (Mlist) {
  106.       Free (Mlist);
  107.       Mlist = Mlist->next;
  108.    }
  109. }
  110.  
  111. exec_command(base)
  112. char *base;
  113. {
  114.    char *str;
  115.    int i;
  116.    if (!H_stack)
  117.       add_history(base);
  118.    strcpy (str = mpush(strlen(base) + 1), base);
  119.    i = e_command(str);
  120.    if (mpop() != str) {
  121.       puts ("POP ERROR");
  122.       fflush (stdout);
  123.    }
  124.    return (1);
  125. }
  126.  
  127. static
  128. e_command(base)
  129. char *base;
  130. {
  131.    char *com, *start, *avline, *alias;
  132.    char *s1, *s2, *s3, *s4;
  133.    int flag = 0;
  134.    int i, pcount, len, ccno;
  135. loop:
  136.    com = breakout (&base, &flag);
  137.    if (*com == '\0') {
  138.       if (flag & FL_EOL)
  139.          return (1);
  140.       goto loop;
  141.    }
  142.    alias = NULL;
  143.    if ((ccno = find_command(com, F_EXACT)) < 0) {
  144.       switch (flag & FL_MASK) {
  145.       case FL_BANG:
  146.          alias = get_history (com);
  147.          replace_head (alias, base, flag);
  148.          break;
  149.       case FL_DOLLAR:
  150.          alias = get_var (LEVEL_SET, com + 1);
  151.          break;
  152.       default:
  153.          alias = get_var (LEVEL_ALIAS, com);
  154.          break;
  155.       }
  156.       if (alias == NULL) {
  157.          if ((ccno = find_command (com, F_ABBR)) < 0) {
  158.             printf ("%s Command Not Found\n", com);
  159.             return (-1);
  160.          } else {
  161.             goto good_command;
  162.          }
  163.       }
  164.  
  165.       if (*alias == '%')
  166.          goto good_command;
  167.  
  168.       start = (!(flag & FL_EOC)) ? base : "";
  169.       while (!(flag & FL_EOC)) {
  170.          flag = FL_OVERIDE;
  171.          breakout (&base, &flag);
  172.       }
  173.  
  174.       com = mpush (strlen(alias) + strlen(start) + 2);
  175.       strcpy (com, alias);
  176.       strcat (com, " ");
  177.       strcat (com, start);
  178.       i = e_command (com);
  179.       if (mpop() != com)
  180.          puts ("ME BAE ERROR");
  181.       if (i < 0)
  182.          return (-1);
  183.       if (flag & FL_EOL)
  184.          return (1);
  185.       goto loop;
  186.    }
  187. good_command:
  188.    if (ccno < 0 || Command[ccno].stat == 0) {
  189.       if (Disable) {
  190.          while (!(flag & FL_EOC))
  191.             breakout (&base, &flag);
  192.          goto eocc;
  193.       }
  194.    }
  195.    pcount = 0;
  196.    i = pcount = 0;
  197.    av[i] = mpush (strlen(com) + 1);
  198.    ++pcount;
  199.    strcpy (av[i++], com);
  200.    while (!(flag & FL_EOC)) {
  201.       com = breakout (&base, &flag);
  202.       if (*com == '\0')
  203.          continue;
  204.       switch (flag & FL_MASK) {
  205.       case FL_DOLLAR:
  206.          av[i] = get_var (LEVEL_SET, com + 1);
  207.          if (av[i] == NULL)
  208.             av[i] = com;
  209.          av[i] = strcpy(mpush (strlen(av[i]) + 1), av[i]);
  210.          ++pcount;
  211.          break;
  212.       case FL_QUOTE:
  213.       default:
  214.          av[i] = com;
  215.          break;
  216.       }
  217.       if (flag & FL_IDOLLAR) {
  218.          for (s1 = av[i]; *s1 && *s1 != '$'; ++s1);
  219.          if (*s1) {
  220.             *s1 = '\0';
  221.             s1 = get_var (LEVEL_SET, s1 + 1);
  222.             if (s1) {
  223.                register char *scr_str = mpush(strlen(av[i])+strlen(s1)+1);
  224.                ++pcount;
  225.                strcpy (scr_str, av[i]);
  226.                strcat (scr_str, s1);
  227.                av[i] = scr_str;
  228.             }
  229.          }
  230.       }
  231.       if (flag & FL_WILD) {   /*  av[i] has a wild card, expand it */
  232.          int eac;
  233.          char **eav, **ebase;
  234.  
  235.          eav = ebase = expand (av[i], &eac);   /* returns malloc'd av list */
  236.          if (eav == NULL) {
  237.             puts ("Null expansion");
  238.             goto fail;
  239.          }
  240.          if (i + eac > MAXAV - 2) {
  241.             free_expand (ebase);
  242.             goto avovr;
  243.          }
  244.          for (; eac; --eac, ++eav) {
  245.             av[i++] = strcpy(mpush(strlen(*eav)+1), *eav);
  246.             ++pcount;
  247.          }
  248.          --i;
  249.          free_expand (ebase);
  250.       }
  251.       if (++i > MAXAV - 2) {
  252. avovr:
  253.          puts ("AV overflow");
  254.          goto fail;
  255.       }
  256.    }
  257.    av[i] = NULL;
  258.    ac = i;
  259.    for (len = 0, i = 0; i < ac; ++i)
  260.       len += strlen(av[i]) + 1;
  261.    avline = mpush (len + 1);
  262.    *avline = '\0';
  263.    for (i = 0; i < ac; ++i) {
  264.       strcat (avline, av[i]);
  265.       if (i + 1 < ac)
  266.          strcat (avline, " ");
  267.    }
  268.    if (*alias) {
  269.       for (s2 = alias; *s2 && *s2 != ' '; ++s2);
  270.       if (*s2) {
  271.          *s2 = '\0';
  272.          s3 = strcpy(mpush(strlen(next_word(avline))+1), next_word(avline));
  273.          s4 = strcpy(malloc(strlen(alias)), alias + 1);
  274.          set_var (LEVEL_SET, s4, s3);
  275.          *s2 = ' ';
  276.          s1 = strcpy(mpush(strlen(s2)+1), s2);
  277.          i = e_command (s1);
  278.          unset_var (LEVEL_SET, s4);
  279.          free (s4);
  280.          if (mpop() != s1)
  281.             puts ("AL-LINE ERROR");
  282.          mpop();
  283.       }
  284.    } else {
  285.       i = -1;
  286.       if (ac < Command[ccno].minargs + 1)
  287.          ierror (NULL, 500);
  288.       else
  289.          i = (*Command[ccno].func)(avline, Command[ccno].val);
  290.    }
  291.    if (mpop() != avline) {
  292.       puts ("AVLINE ERROR");
  293. fail:
  294.       i = -1;
  295.    }
  296.    while (pcount--)
  297.       mpop();
  298.    if (i < 0)
  299.       return (i);
  300. eocc:
  301.    if (flag & FL_EOL)
  302.       return (1);
  303.    goto loop;
  304. }
  305.  
  306. static char *
  307. breakout(base, flag)
  308. register int *flag;
  309. char **base;
  310. {
  311.    register char *str, *scr;
  312.    register int oflag = *flag;
  313.  
  314. loop:
  315.    *flag = 0;
  316.    str = *base;
  317.    while (*str == ' ' || *str == 9)
  318.       ++str;
  319.    switch (*str) {
  320.    case '\0':
  321.       *flag = FL_EOC | FL_EOL;
  322.       *base = str;
  323.       return (str);
  324.    case '*':
  325.    case '?':
  326.       *flag = FL_WILD;
  327.       break;
  328.    case ';':
  329.       *flag = FL_EOC;
  330.       *str = '\0';
  331.       *base = str + 1;
  332.       return (str);
  333.    case '\"':
  334.       *flag = FL_QUOTE;
  335.       break;
  336.    case '$':
  337.       *flag = FL_DOLLAR;
  338.       break;
  339.    case '%':
  340.       *flag = FL_PERCENT;
  341.       break;
  342.    case '!':
  343.       *flag = FL_BANG;
  344.       break;
  345.    default:
  346.       break;
  347.    }
  348.    scr = str;
  349.    for (;;) {
  350.       switch (*scr) {
  351.       case '$':
  352.          if (scr != str)
  353.             *flag |= FL_IDOLLAR;
  354.          ++scr;
  355.          break;
  356.       case '*':
  357.       case '?':
  358.          *flag |= FL_WILD;
  359.          ++scr;
  360.          break;
  361.       case ' ':
  362.       case 9:
  363.          if (!(oflag & FL_OVERIDE))
  364.             *scr = '\0';
  365.          *base = scr + 1;
  366.          return (str);
  367.       case '\"':                    /* Quote */
  368.          del_char(scr);
  369.          while (*scr && *scr != '\"') {
  370.             if (*scr == '\\') {
  371.                del_char(scr);
  372.                if (*scr)
  373.                   ++scr;
  374.             } else {
  375.                ++scr;
  376.             }
  377.          }
  378.          if (*scr == '\"')
  379.             del_char(scr);
  380.          break;
  381.       case '\0':
  382.          *flag |= FL_EOL | FL_EOC;
  383.          *base = scr;
  384.          return (str);
  385.       case ';':
  386.          *flag |= FL_EOC;
  387.          *base = scr + 1;
  388.          *scr = '\0';
  389.          return (str);
  390.       case '^':
  391.          ++scr;
  392.          if (*scr) {
  393.             *(scr - 1) = *scr & 0x1f;
  394.             del_char (scr);
  395.          }
  396.          break;
  397.       case '\\':
  398.          del_char(scr);
  399.          if (*scr)
  400.             ++scr;
  401.          break;
  402.       default:
  403.          ++scr;
  404.       }
  405.    }
  406. }
  407.  
  408. del_char(str)
  409. register char *str;
  410. {
  411.    for (; *str; ++str)
  412.       str[0] = str[1];
  413. }
  414.  
  415. static
  416. find_command(str, arg)
  417. char *str;
  418. {
  419.    int i;
  420.    int len = strlen(str);
  421.  
  422.    if (*str >= '0'  &&  *str <= '9')
  423.       return (1);
  424.    for (i = 0; Command[i].func; ++i) {
  425.       if (strncmp (str, Command[i].name, len) == 0) {
  426.          if (arg == F_ABBR)
  427.             return (i);
  428.          if (strcmp (str, Command[i].name) == 0)
  429.             return (i);
  430.          return (-1);
  431.       }
  432.    }
  433.    if (arg == F_ABBR)
  434.       return (0);
  435.    return (-1);
  436. }
  437.  
  438.  
  439.